using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ServiceStack.Reflection
{
	public static class DelegateFactory
	{
		public delegate object LateBoundMethod(object target, object[] arguments);
		public delegate void LateBoundVoid(object target, object[] arguments);
		public static DelegateFactory.LateBoundMethod Create(MethodInfo method)
		{
			ParameterExpression parameterExpression;
			ParameterExpression parameterExpression2;
			return Expression.Lambda<DelegateFactory.LateBoundMethod>(Expression.Convert(Expression.Call(Expression.Convert(parameterExpression, method.DeclaringType), method, DelegateFactory.CreateParameterExpressions(method, parameterExpression2)), typeof(object)), new ParameterExpression[]
			{
				parameterExpression,
				parameterExpression2
			}).Compile();
		}
		private static Expression[] CreateParameterExpressions(MethodInfo method, Expression argumentsParameter)
		{
			return method.GetParameters().Select((ParameterInfo parameter, int index) => Expression.Convert(Expression.ArrayIndex(argumentsParameter, Expression.Constant(index)), parameter.ParameterType)).ToArray<UnaryExpression>();
		}
		public static DelegateFactory.LateBoundVoid CreateVoid(MethodInfo method)
		{
			ParameterExpression parameterExpression;
			ParameterExpression parameterExpression2;
			return Expression.Lambda<DelegateFactory.LateBoundVoid>(Expression.Convert(Expression.Call(Expression.Convert(parameterExpression, method.DeclaringType), method, DelegateFactory.CreateParameterExpressions(method, parameterExpression2)), method.ReturnParameter.ParameterType), new ParameterExpression[]
			{
				parameterExpression,
				parameterExpression2
			}).Compile();
		}
	}
}
